package Infinite::Sequence::Set;
use Infinite::Sequence::Guard::Ascending;
use Infinite::Sequence::SetOperation;
use Exporter qw{import};
use overload
        '+' => sub{ overload_operator( q{union}, @_ ) },
        '-' => sub{ overload_operator( q{complement}, @_ ) },
        'x' => sub{ overload_operator( q{intersection}, @_ ) }
;

our @EXPORT_OK = qw{SET};

sub new { shift; SET( @_ ) }
sub SET {
    my $this = bless {}, __PACKAGE__;
    
    if( @_ == 1 ) {
    	$this->{sequence} = new Infinite::Sequence::Guard::Ascending(
    		Infinite::Sequence::cast( shift ) ) 
    } elsif( @_ == 3 ) {
    	( $this->{A}, $this->{B}, $this->{op} ) = @_
    } else {
    	die q{expecting 1 or 3 arguments}
    }
    
    $this
}

sub overload_operator {
    my( $op, $A, $B, $swapped ) = @_;
    die q{sets swapped} if $swapped;
    die q{can only operate on sets} unless ref( $B ) && $B->isa( __PACKAGE__ );
	SET( $A, $B, $op )
}

sub sequence {
	my( $this ) = @_;
	
	if( exists $this->{sequence} ) {
		$this->{sequence}
	} else {
	    new Infinite::Sequence::SetOperation( $this->{A}->sequence, $this->{B}->sequence, $this->{op} )
	}
}

1;